// src/sql/parser/mod.rs

use std::iter::Peekable;
use lexer::Lexer;
use crate::error::{Error, Result};
use crate::sql::parser::ast::Column;
use crate::sql::parser::lexer::{Keyword, Token};
use crate::sql::types::DataType;

mod lexer;
pub mod ast;

pub struct Parser<'a> {
    lexer: Peekable<Lexer<'a>>,
}

impl<'a> Parser<'a> {
    pub fn new(input: &'a str) -> Self {
        Parser {
            lexer: Lexer::new(input).peekable(),
        }
    }

    // 解析, 获取抽象语法树 AST
    pub fn parse(&mut self) -> Result<ast::Statement> {
        let stmt = self.parse_statement()?;
        // 期望sql语句最后有个分号
        self.next_expect(Token::Semicolon);
        // 分号后不能有其他字符
        if let Some(token) = self.peek()? {
            return Err(Error::Parse(
                format!("[Parser] Unexpected token {}", token)
            ));
        }
        Ok(stmt)
    }

    // 解析语句
    fn parse_statement(&mut self) -> Result<ast::Statement> {
        // 查看第一个token类型
        match self.peek()? {
            Some(Token::Keyword(Keyword::Create)) => self.parse_ddl(),
            Some(Token::Keyword(Keyword::Select)) => self.parse_select(),
            Some(Token::Keyword(Keyword::Insert)) => self.parse_insert(),
            Some(t) => Err(Error::Parse(
                format!("[Parser] Unexpected token {:?}", t)
            )),
            None => Err(Error::Parse(
                format!("[Parser] Unexpected end of input")
            )),
        }
    }

    // 解析 DDL 建表语句
    fn parse_ddl(&mut self) -> Result<ast::Statement> {
        match self.next()? {
            Token::Keyword(Keyword::Create) =>
                match self.next()? {
                    // 再看一下下一个, 如果是table就是对的
                    Token::Keyword(Keyword::Table) => self.parse_ddl_create_table(),
                    token => Err(Error::Parse(
                        format!("[Parser] Unexpected token {}", token)
                    )),
                },
            token => Err(Error::Parse(
                format!("[Parser] Unexpected token {}", token)
            )),
        }
    }

    // 解析 insert 语句
    fn parse_insert(&mut self) -> Result<ast::Statement> {
        // 插入语句
        self.next_expect(Token::Keyword(Keyword::Insert))?;
        self.next_expect(Token::Keyword(Keyword::Into))?;

        // 表名
        let table_name = self.next_ident()?;

        // 查看是否给指定的列进行 insert
        // 如果接下来是 (
        let columns = if self.next_if_token(Token::OpenParen).is_some() {
            let mut cols = Vec::new();
            loop {
                cols.push(self.next_ident()?.to_string());
                match self.next()? {
                    // insert into xxx(a,b,c) values (a,b,c)
                    // 如果下一个是 )  表明已经解析完所有的列了
                    Token::CloseParen => break,
                    Token::Comma => {}
                    token => {
                        return Err(Error::Parse(
                            format!("[Parser] Unexpected token {}", token)
                        ))
                    }
                }
            }

            Some(cols)
        } else {
            None
        };

        // 解析values信息
        self.next_expect(Token::Keyword(Keyword::Values));
        // insert into tbl(a,b,c) values (1,2,3),(4,5,6)
        let mut values = Vec::new();
        // 遍历解析 values 后的所有括号
        loop {
            self.next_expect(Token::OpenParen)?;
            let mut exprs = Vec::new();
            // 解析 (1,2,3)
            loop {
                exprs.push(self.parse_expression()?);
                match self.next()? {
                    // insert into xxx(a,b,c) values (a,b,c)
                    // 如果下一个是 )  表明已经解析完所有的列了
                    Token::CloseParen => break,
                    Token::Comma => {}
                    token => {
                        return Err(Error::Parse(
                            format!("[Parser] Unexpected token {}", token)
                        ))
                    }
                }
            }
            values.push(exprs);
            // 如果后面没有逗号, 列解析完成, 退出
            if self.next_if_token(Token::Comma).is_none() {
                break;
            }
        }

        Ok(ast::Statement::Insert { table_name, columns, values })
    }

    // 解析 select 语句
    fn parse_select(&mut self) -> Result<ast::Statement> {
        // select * from
        self.next_expect(Token::Keyword(Keyword::Select));
        self.next_expect(Token::Asterisk)?;
        self.next_expect(Token::Keyword(Keyword::From));

        // 表名
        let table_name = self.next_ident()?;
        Ok(ast::Statement::Select { table_name })
    }

    // 解析 create table 语句
    fn parse_ddl_create_table(&mut self) -> Result<ast::Statement> {
        // 期望是table名
        let table_name = self.next_ident()?;
        // 表名之后是括号
        self.next_expect(Token::OpenParen)?;

        // 解析列信息
        let mut columns = Vec::new();
        loop {
            columns.push(self.parse_ddl_column()?);
            // 如果后面没有逗号, 列解析完成, 退出
            if self.next_if_token(Token::Comma).is_none() {
                break;
            }
        }

        self.next_expect(Token::CloseParen)?;
        Ok(ast::Statement::CreateTable {
            name: table_name,
            columns,
        })
    }

    // 解析列信息
    fn parse_ddl_column(&mut self) -> Result<ast::Column> {
        let mut column = Column {
            name: self.next_ident()?,
            datatype: match self.next()? {
                Token::Keyword(Keyword::Int) | Token::Keyword(Keyword::Integer) => DataType::Integer,
                Token::Keyword(Keyword::Bool) | Token::Keyword(Keyword::Boolean) => DataType::Boolean,
                Token::Keyword(Keyword::Float) | Token::Keyword(Keyword::Double) => DataType::Float,
                Token::Keyword(Keyword::String) | Token::Keyword(Keyword::Text) | Token::Keyword(Keyword::Varchar)
                => DataType::String,
                token => return Err(Error::Parse(
                    format!("[Parser] Unexpected token {}", token)
                )),
            },
            nullable: None,
            default: None,
        };

        // 解析列的默认值, 以及是否可以为null
        while let Some(Token::Keyword(keyword)) = self.next_if_keyword() {
            match keyword {
                // 如果下一个关键字是null, 表示字段可以为空
                Keyword::Null => column.nullable = Some(true),
                Keyword::Not => {
                    self.next_expect(Token::Keyword(Keyword::Null))?;
                    column.nullable = Some(false);
                }
                Keyword::Default => column.default = Some(self.parse_expression()?),
                k => return Err(Error::Parse(
                    format!("[Parser] Unexpected keyword {}", k)
                )),
            }
        }

        Ok(column)
    }

    // 解析表达式
    fn parse_expression(&mut self) -> Result<ast::Expression> {
        Ok(match self.next()? {
            Token::Number(n) => {
                // 该字符串的所有字符是否都满足ascii数字
                if n.chars().all(|c| c.is_ascii_digit()) {
                    // 整数
                    ast::Consts::Integer(n.parse()?).into()
                } else {
                    // 浮点数
                    ast::Consts::Float(n.parse()?).into()
                }
            }
            Token::String(s) => ast::Consts::String(s).into(),
            Token::Keyword(Keyword::True) => ast::Consts::Boolean(true).into(),
            Token::Keyword(Keyword::False) => ast::Consts::Boolean(false).into(),
            Token::Keyword(Keyword::Null) => ast::Consts::Null.into(),
            t => return Err(Error::Parse(
                format!("[Parser] Unexpected expression token {}", t)
            )),
        })
    }

    // 获取下一个
    fn peek(&mut self) -> Result<Option<Token>> {
        // 转换返回类型 Result(...)
        self.lexer.peek().cloned().transpose()
    }

    fn next(&mut self) -> Result<Token> {
        self.lexer.next().unwrap_or_else(|| Err(Error::Parse(
            // 如果返回的不是token而是空, 则返回错误
            format!("[Parser] Unexpected end of input")
        )))
    }

    // 获取下一个标识符, 如果不是标识符, 则返回错误
    fn next_ident(&mut self) -> Result<String> {
        // ?:
        // 如果表达式的值是 Ok(value) 或 Some(value)，则解包并返回 value
        // 如果表达式的值是 Err(err) 或 None，则提前返回整个函数，返回值为当前表达式的值（即 Err(err) 或 None）。
        match self.next()? {
            Token::Ident(ident) => Ok(ident),
            token => Err(Error::Parse(
                format!("[Parser] Expected ident, got token {}", token)
            )),
        }
    }

    // 查看下一个, 如果不是期望的, 则返回错误
    fn next_expect(&mut self, expected: Token) -> Result<()> {
        let token = self.next()?;
        if token != expected {
            return Err(Error::Parse(
                format!("[Parser] Expected {}, got token {}", expected, token)
            ));
        }
        Ok(())
    }

    // 满足传入函数的条件才跳转下一个
    fn next_if<F: Fn(&Token) -> bool>(&mut self, predicate: F) -> Option<Token> {
        self.peek().unwrap_or(None).filter(|t| predicate(t))?;
        self.next().ok()
    }

    // 如果下一个是关键字, 则跳转
    fn next_if_keyword(&mut self) -> Option<Token> {
        self.next_if(|t| matches!(t, Token::Keyword(_)))
    }

    // 如果下一个是指定token, 则跳转
    fn next_if_token(&mut self, token: Token) -> Option<Token> {
        self.next_if(|t| t == &token)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_parser_create_table() -> Result<()> {
        let sql1 = "CREATE TABLE tb1 (
                a int default 100,
                b float not null,
                c varchar null,
                d bool default true
            );
        ";
        let stmt1 = Parser::new(sql1).parse()?;


        let sql2 = "CREATE    TABLE tb1 (
                a int          default 100,
                b  float  not        null,
                c varchar null,
                d   bool       default    true
            );
        ";
        let stmt2 = Parser::new(sql2).parse()?;
        assert_eq!(stmt1, stmt2);


        let sql3 = "CREATE    tab tb1 (
                a int          default 100,
                b  float  not        null,
                c varchar null,
                d   bool       default    true
            );
        ";

        let stmt3 = Parser::new(sql3).parse();
        assert!(stmt3.is_err());

        Ok(())
    }

    #[test]
    fn test_parser_insert() -> Result<()> {
        let sql1 = "INSERT INTO tb1  VALUES (1, 2.0, '3');";
        let stmt1 = Parser::new(sql1).parse()?;
        // println!("{:?}", stmt1);
        assert_eq!(stmt1, ast::Statement::Insert {
            table_name: "tb1".to_string(),
            columns: None,
            values: vec![vec![
                ast::Expression::Consts(
                    ast::Consts::Integer(1)
                ),
                ast::Expression::Consts(
                    ast::Consts::Float(2.0)
                ),
                ast::Expression::Consts(
                    ast::Consts::String("3".to_string())
                ),
            ]],
        });

        let sql2 = "INSERT INTO tb1 (a, b, c)  VALUES (1, 2.0, '3'), (4,2.3,'3');";
        let stmt2 = Parser::new(sql2).parse()?;
        // println!("{:?}", stmt2);
        assert_eq!(stmt2, ast::Statement::Insert {
            table_name: "tb1".to_string(),
            columns: Some(vec![
                "a".to_string(),
                "b".to_string(),
                "c".to_string(),
            ]),
            values: vec![
                vec![
                    ast::Expression::Consts(
                        ast::Consts::Integer(1)
                    ),
                    ast::Expression::Consts(
                        ast::Consts::Float(2.0)
                    ),
                    ast::Expression::Consts(
                        ast::Consts::String("3".to_string())
                    ),
                ],
                vec![
                    ast::Expression::Consts(
                        ast::Consts::Integer(4)
                    ),
                    ast::Expression::Consts(
                        ast::Consts::Float(2.3)
                    ),
                    ast::Expression::Consts(
                        ast::Consts::String("3".to_string())
                    ),
                ],
            ],
        });

        Ok(())
    }

    #[test]
    fn test_parser_select() -> Result<()> {
        let sql1 = "SELECT * FROM tb1;";
        let stmt1 = Parser::new(sql1).parse()?;
        assert_eq!(stmt1, ast::Statement::Select {
            table_name: "tb1".to_string(),
        });

        Ok(())
    }
}